{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# importing libraries\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn import preprocessing \n",
    "import numpy as np\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.tree import DecisionTreeClassifier\n",
    "from sklearn.metrics import accuracy_score\n",
    "from sklearn.metrics import f1_score\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.decomposition import PCA\n",
    "from sklearn import preprocessing\n",
    "\n",
    "from sklearn.preprocessing import OneHotEncoder \n",
    "import random\n",
    "import numpy as np\n",
    "from sklearn.datasets import make_circles, make_moons\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "from sklearn.metrics import f1_score, precision_score\n",
    "from sklearn.datasets import make_circles, make_moons\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib\n",
    "import numpy as np\n",
    " \n",
    "import random\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "from torch.utils.data import DataLoader\n",
    "import matplotlib.pyplot as plt\n",
    "from torch import Tensor\n",
    "import torch.optim as optim\n",
    "import torch.nn.functional as Fnc\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import torchvision.datasets as datasets\n",
    "from IPython.core.debugger import set_trace\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.decomposition import PCA\n",
    "import matplotlib\n",
    "from torch.autograd.variable import Variable\n",
    "import sys\n",
    "#################################################"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Loading Dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 442
    },
    "colab_type": "code",
    "executionInfo": {
     "elapsed": 1524,
     "status": "error",
     "timestamp": 1575151838286,
     "user": {
      "displayName": "Nur Imtiazul Haque",
      "photoUrl": "",
      "userId": "15560043854638298091"
     },
     "user_tz": 300
    },
    "id": "kDVtb4eNXUVM",
    "outputId": "a7da0aa2-f7a1-4b01-b6a3-02037660aaa6"
   },
   "outputs": [],
   "source": [
    "############################   DATA SET LOAD  #########################\n",
    "\n",
    "\n",
    "### for sorting the the labeled data based on support\n",
    "def sortingFunction(data):\n",
    "    return data.shape[0]\n",
    "\n",
    "\n",
    "#### label coding for nominal values\n",
    "def label_coding(label):\n",
    "    dataset[label]= label_encoder.fit_transform(dataset[label]) \n",
    "    dataset[label].unique()\n",
    "    \n",
    "### splitting dataset \n",
    "def crop_dataset(len_dataset):\n",
    "    for label in range(len_dataset):\n",
    "        temp_dataframe=dataset[dataset['label']==label]\n",
    "        try:\n",
    "            if temp_dataframe.shape[0]>8:\n",
    "                _ ,temp_dataframe = train_test_split(temp_dataframe,test_size =.25)\n",
    "            temp_train ,temp_test = train_test_split(temp_dataframe,test_size=0.25)\n",
    "            list_train.append(temp_train)\n",
    "            list_test.append(temp_test)\n",
    "        except:\n",
    "            print(\"Error for \"+str(label))\n",
    "        \n",
    "### producing new samples        \n",
    "def new_sample_generation(x,y,z):\n",
    "    need=500-x if x<=500 else 0\n",
    "    #print(\"n_sample: \"+str(x)+\" max_sample: \"+str(y)+\" need_to_create: \"+str(need))\n",
    "    \n",
    "    \n",
    "### importing dataset\n",
    "dataset = pd.read_csv('kddcup99_csv.csv')\n",
    "\n",
    "### label encoding\n",
    "label_encoder = preprocessing.LabelEncoder() \n",
    "label_coding('protocol_type')\n",
    "label_coding('service')\n",
    "label_coding('flag')\n",
    "label_coding('label')\n",
    "\n",
    "### extracting features\n",
    "X=dataset.iloc[:,:-1]\n",
    "X=X.values\n",
    "scaler = preprocessing.StandardScaler()\n",
    "scaler.fit(X)\n",
    "X=scaler.transform(X)\n",
    "\n",
    "\n",
    "################################   PCA #####################################################\n",
    "### dimention reduction\n",
    "\n",
    "number_of_components=20\n",
    "pca = PCA(n_components=number_of_components)\n",
    "columns_array=[]\n",
    "for i in range (number_of_components):\n",
    "    columns_array.append(\"principal_Component\"+str(i+1))\n",
    "    \n",
    "principalComponents = pca.fit_transform(X)\n",
    "principalDf = pd.DataFrame(data = principalComponents\n",
    "              , columns = columns_array)\n",
    "\n",
    "finalDf = pd.concat([principalDf, dataset[['label']]], axis = 1)\n",
    "dataset=finalDf\n",
    "\n",
    "#############################  CROP DATA SET up to 15 Labels  ###########################\n",
    "len_dataset= len(dataset.label.unique())\n",
    "list_train,list_test=[],[]\n",
    "    \n",
    "crop_dataset(len_dataset)\n",
    "\n",
    "list_train.sort(key=sortingFunction,reverse=True)\n",
    "list_test.sort(key=sortingFunction,reverse=True)\n",
    "\n",
    "train_dataframe=list_train[0]\n",
    "test_dataframe=list_test[0]\n",
    "\n",
    "\n",
    "# for taking top 15 labels\n",
    "labels_to_consider = 15\n",
    "max_samples = list_train[0].shape[0]\n",
    "\n",
    "for i in range(1,labels_to_consider):\n",
    "    new_sample_generation(len(list_train[i]),max_samples,int((max_samples-len(list_train[i]))*.5))\n",
    "    train_dataframe=pd.concat([train_dataframe,list_train[i]])\n",
    "    test_dataframe=pd.concat([test_dataframe,list_test[i]])\n",
    "partial_dataframe=pd.concat([train_dataframe,test_dataframe])\n",
    "\n",
    "#print(len(test_dataframe.label.unique()))\n",
    "\n",
    "####################################  Generating Numpy Array X,y ###################\n",
    "\n",
    "x_train=np.array(train_dataframe.iloc[:,:-1])\n",
    "x_test=np.array(test_dataframe.iloc[:,:-1])\n",
    "y_train=np.array(train_dataframe.iloc[:,-1])\n",
    "y_test=np.array(test_dataframe.iloc[:,-1])   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### for extracting data from classification report\n",
    "def CR_mat(y_true,y_pred):\n",
    "    import re\n",
    "    from sklearn.metrics import classification_report\n",
    "    report=classification_report(y_true, y_pred)\n",
    "    classification_list=[]\n",
    "    lines=report.split(\"\\n\")[2:-5]\n",
    "    for line in lines:\n",
    "        line=re.sub(' +', ' ', line)\n",
    "        words=line.split(\" \")\n",
    "        if len(words)<5:\n",
    "            continue\n",
    "        print(words)\n",
    "        classification_list.append(words[1:])\n",
    "    classification_mat=np.array(classification_list).astype(np.float)\n",
    "    return classification_mat"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "Bdgpb7HSXUVY"
   },
   "source": [
    "# Intrusion Detection System"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#####################   IDS ANN Model   ########################\n",
    "\n",
    "class ANN(nn.Module):\n",
    "   \n",
    "    def __init__(self):\n",
    "        super(ANN,self).__init__()\n",
    "        \n",
    "        nodes_layer_0 = 20\n",
    "        nodes_layer_1 = 50\n",
    "        nodes_layer_2 = 50\n",
    "        nodes_layer_3 = 23\n",
    "       \n",
    "        # input has two features and\n",
    "        self.layer1 = nn.Linear(nodes_layer_0,nodes_layer_1)\n",
    "        self.layer2 = nn.Linear(nodes_layer_1,nodes_layer_2)\n",
    "        self.layer3 = nn.Linear(nodes_layer_2,nodes_layer_3)\n",
    "\n",
    "    #forward propagation    \n",
    "    def forward(self,x):\n",
    "        #output of layer 1       \n",
    "        z1 = self.layer1(x)\n",
    "        a1 = Fnc.tanh(z1)\n",
    "        # output of layer 2\n",
    "        z2 = self.layer2(a1)\n",
    "        a2 = Fnc.tanh(z2)\n",
    "        z3 = self.layer3(a2)\n",
    "        \n",
    "        return z3\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "wv0wDJmuXUVc"
   },
   "outputs": [],
   "source": [
    "\n",
    "####################  DATA LOADING   #####################\n",
    "\n",
    "x_train = torch.from_numpy(x_train).type(torch.FloatTensor)\n",
    "x_test = torch.from_numpy(x_test).type(torch.FloatTensor)\n",
    "\n",
    "y_train = torch.from_numpy(y_train).type(torch.LongTensor)\n",
    "y_test = torch.from_numpy(y_test).type(torch.LongTensor)\n",
    "\n",
    "Training_data = [(x, y) for x, y in zip(x_train,y_train)]\n",
    "Testing_data = [(x, y) for x, y in zip(x_test,y_test)]\n",
    "        \n",
    "class Data_Loader():\n",
    "    \n",
    "    def __init__(self,data_list):       \n",
    "        self.data=data_list\n",
    "    \n",
    "    def __len__(self):\n",
    "        return len(self.data)\n",
    "    \n",
    "    def __getitem__(self, index):\n",
    "        img = self.data[index][0]\n",
    "        img_tensor = Tensor(img).float()\n",
    "        label = self.data[index][1]\n",
    "        return (img_tensor, label)\n",
    "\n",
    "#######################  Train and Test Data Set  ##########################\n",
    "\n",
    "Training_DataSet=Data_Loader(Training_data)\n",
    "Testing_DataSet=Data_Loader(Testing_data)\n",
    "\n",
    "train_loader = DataLoader(dataset=Training_DataSet, batch_size=5000, shuffle=True)\n",
    "testing_loader = DataLoader(dataset=Testing_DataSet, batch_size=len(Testing_DataSet), shuffle=True)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "WFXY2FhlXUVf"
   },
   "outputs": [],
   "source": [
    "########################## Running IDS Model ######################    \n",
    "maxEpochforIDS=200\n",
    "model = ANN()\n",
    "F1_list_before=[]\n",
    "Pre_list=[]\n",
    "Report_before=[]\n",
    "\n",
    " \n",
    "optimizer = optim.Adam(model.parameters(), lr = 0.001)\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "\n",
    "\n",
    "\n",
    "for epoch in range(maxEpochforIDS):\n",
    "    correct_cnt, ave_loss = 0, 0\n",
    "    total_cnt = 0\n",
    "    for batch_idx, (x, target) in enumerate(train_loader):\n",
    "        optimizer.zero_grad()\n",
    "        out = model(x)\n",
    "        loss = criterion(out, target)\n",
    "        _, pred_label = torch.max(out.data, 1)\n",
    "        total_cnt += x.shape[0]\n",
    "        correct_cnt+= (pred_label == target).sum().item()\n",
    "        ave_loss = ave_loss * 0.9 + loss.item() * 0.1\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        if (epoch+1) % 20 == 0 or (batch_idx+1) == len(train_loader):\n",
    "            continue\n",
    "            print('==>>> epoch: {}, batch index: {}, train loss: {:.6f}, acc: {:.3f}'.format(\n",
    "                epoch, batch_idx+1, ave_loss, correct_cnt*1.0/total_cnt))\n",
    "    # testing\n",
    "    correct_cnt, ave_loss = 0, 0\n",
    "    total_cnt = 0\n",
    "    \n",
    "    \n",
    "    for batch_idx, (x, target) in enumerate(testing_loader):\n",
    "        #print(batch_idx,x.shape, target.shape)\n",
    "        out = model(x)\n",
    "        loss = criterion(out, target)\n",
    "        _, pred_label = torch.max(out.data, 1)\n",
    "        total_cnt += x.shape[0]\n",
    "#       print(target.data)\n",
    "        correct_cnt += (pred_label == target).sum().item()\n",
    "        # smooth average\n",
    "        ave_loss = ave_loss * 0.9 + loss.item() * 0.1\n",
    "       \n",
    "        if(epoch+1) % 1 == 0 or (batch_idx+1) == len(testing_loader):\n",
    "            F1= f1_score(target, pred_label, average=None)\n",
    "            Pre=precision_score(target, pred_label, average=None)\n",
    "            #Precission=precision_score(target, pred_label, average='macro')\n",
    "\n",
    "\n",
    "            #print('==>>> epoch: {}, batch index: {}, test loss: {:.6f},'.format(\n",
    "                #epoch, batch_idx+1, ave_loss, correct_cnt * 1.0 / total_cnt))\n",
    "            #print('F1',F1)\n",
    "            if np.array(F1).size!=labels_to_consider:\n",
    "                continue\n",
    "            F1_list_before.append(np.array(F1))\n",
    "            Pre_list.append(Pre)\n",
    "            plt.plot()\n",
    "            plt.plot(F1_list_before)\n",
    "            plt.show()\n",
    "            ################################\n",
    "            y_true =target\n",
    "            y_pred = pred_label\n",
    "            Report_before.append(CR_mat(y_true,y_pred))\n",
    "#########################################################################################\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "wGr9EZ0PXUVj"
   },
   "outputs": [],
   "source": [
    "##################  EVALUATING PERFORMANCE of IDS ########################\n",
    "\n",
    "from sklearn.metrics import classification_report\n",
    "y_true =target\n",
    "y_pred = pred_label\n",
    "print(classification_report(y_true, y_pred))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### Classification report before GAN\n",
    "import re\n",
    "report=classification_report(y_true, y_pred)\n",
    "classification_list=[]\n",
    "lines=report.split(\"\\n\")[2:-5]\n",
    "for line in lines:\n",
    "    line=re.sub(' +', ' ', line)\n",
    "    words=line.split(\" \")\n",
    "    if len(words)<5:\n",
    "        continue\n",
    "    print(words)\n",
    "    classification_list.append(words[1:])\n",
    "classification_mat=np.array(classification_list).astype(np.float)\n",
    "np.savetxt(\"classification_mat_before.txt\",classification_mat, fmt='%0.2f')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# GAN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "dQqe1ItqXUVp"
   },
   "outputs": [],
   "source": [
    "\n",
    "class Data_Loader(): \n",
    "    def __init__(self,data_list):       \n",
    "        self.data=data_list\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.data)\n",
    "\n",
    "    def __getitem__(self, index):\n",
    "        img = self.data[index][0]\n",
    "        img_tensor = Tensor(img).float()\n",
    "        label = self.data[index][1]\n",
    "        return (img_tensor, label)\n",
    "\n",
    "def noise(size):\n",
    "    '''\n",
    "    Generates a 1-d vector of gaussian sampled random values\n",
    "    '''\n",
    "    n = Variable(torch.randn(size, 5))\n",
    "    return n\n",
    "\n",
    "def ones_target(size):\n",
    "    '''\n",
    "    Tensor containing zeros, with shape = size\n",
    "    '''\n",
    "    data = Variable(torch.ones(size, 1))\n",
    "    return data\n",
    "\n",
    "def zeros_target(size):\n",
    "    '''\n",
    "    Tensor containing zeros, with shape = size\n",
    "    '''\n",
    "    data = Variable(torch.zeros(size, 1))\n",
    "    \n",
    "    return data\n",
    "\n",
    "def true_target(y):\n",
    "    '''\n",
    "    Tensor containing zeros, with shape = size\n",
    "    '''\n",
    "    data= Variable(torch.from_numpy(y).type(torch.FloatTensor))\n",
    "    return data\n",
    "\n",
    "\n",
    "#### model generation for discriminator\n",
    "class DiscriminatorNet(torch.nn.Module):\n",
    "    \"\"\"\n",
    "    A three hidden-layer discriminative neural network\n",
    "    \"\"\"\n",
    "    def __init__(self):\n",
    "        super(DiscriminatorNet, self).__init__()\n",
    "        n_features = 20\n",
    "        n_out = 1\n",
    "        \n",
    "        \n",
    "        self.hidden0 = nn.Sequential( \n",
    "            nn.Linear(n_features, 50),\n",
    "            nn.Tanh()\n",
    "            #nn.Dropout(0.3)\n",
    "        )\n",
    "        \n",
    "        self.hidden1 = nn.Sequential(\n",
    "            nn.Linear(50, 50),\n",
    "            nn.Tanh()\n",
    "            #nn.Dropout(0.3)\n",
    "        )\n",
    "        \n",
    "        self.out = nn.Sequential(\n",
    "            torch.nn.Linear(50, n_out),\n",
    "            torch.nn.Sigmoid()\n",
    "        )\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = self.hidden0(x)\n",
    "        #print(\"Discriminator\", x)\n",
    "        x = self.hidden1(x)\n",
    "        #x = self.hidden2(x)\n",
    "        x = self.out(x)\n",
    "        return x\n",
    "\n",
    "#### model generation for generator\n",
    "class GeneratorNet(torch.nn.Module):\n",
    "    \"\"\"\n",
    "    A three hidden-layer generative neural network\n",
    "    \"\"\"\n",
    "    def __init__(self):\n",
    "        super(GeneratorNet, self).__init__()\n",
    "        n_noise = 5\n",
    "        n_out = 20\n",
    "        \n",
    "        self.hidden0 = nn.Sequential(\n",
    "            nn.Linear(n_noise, 50),\n",
    "            nn.Tanh()\n",
    "        )\n",
    "        \n",
    "        self.hidden1 = nn.Sequential(            \n",
    "            nn.Linear(50, 50),\n",
    "            nn.Tanh()\n",
    "        )\n",
    "        \n",
    "        self.out = nn.Sequential(\n",
    "            nn.Linear(50, n_out),\n",
    "            nn.Tanh()\n",
    "        )\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = self.hidden0(x)\n",
    "        x = self.hidden1(x)\n",
    "        \n",
    "        #x = self.hidden2(x)\n",
    "        #print(\"Generator\", x)\n",
    "        \n",
    "        x = self.out(x)\n",
    "        return x\n",
    "    \n",
    "# training discriminator \n",
    "def train_discriminator(optimizer, real_data, fake_data, y_real):\n",
    "    \n",
    "    N = real_data.size(0)\n",
    "    # Reset gradients\n",
    "    optimizer.zero_grad()\n",
    "\n",
    "    # 1.1 Train on Real Data\n",
    "    prediction_real = discriminator(real_data)\n",
    "    # Calculate error and backpropagate\n",
    "    error_real = loss(prediction_real, true_target(y_real))\n",
    "    error_real.backward()\n",
    "    \n",
    "    # 1.2 Train on Fake Data\n",
    "    prediction_fake = discriminator(fake_data)\n",
    "    # Calculate error and backpropagate\n",
    "    error_fake = loss(prediction_fake, zeros_target(N))\n",
    "    error_fake.backward()\n",
    "    \n",
    "    # 1.3 Update weights with gradients\n",
    "    optimizer.step()\n",
    "    \n",
    "    # Return error and predictions for real and fake inputs\n",
    "    return error_real + error_fake, prediction_real, prediction_fake\n",
    "\n",
    "# training generator\n",
    "def train_generator(optimizer, fake_data):\n",
    "    N = fake_data.size(0)\n",
    "    # Reset gradients\n",
    "    optimizer.zero_grad()\n",
    "    # Sample noise and generate fake data\n",
    "    prediction = discriminator(fake_data)\n",
    "    # Calculate error and backpropagate\n",
    "    error = loss(prediction, ones_target(N))\n",
    "    error.backward()\n",
    "    # Update weights with gradients\n",
    "    optimizer.step()\n",
    "    # Return error\n",
    "    return error\n",
    "\n",
    "#################  Partial Data  ##################\n",
    "y_partial=np.array(partial_dataframe.iloc[:,-1])\n",
    "x_partial=np.array(partial_dataframe.iloc[:,:-1])\n",
    "#*************************************************\n",
    "x_train=np.array(train_dataframe.iloc[:,:-1])\n",
    "x_test=np.array(test_dataframe.iloc[:,:-1])\n",
    "y_train=np.array(train_dataframe.iloc[:,-1])\n",
    "y_test=np.array(test_dataframe.iloc[:,-1])  \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "########################   Finding Weak labels ##############################\n",
    "\n",
    "classification_mat=np.array(classification_list).astype(np.float)\n",
    "numOfSamples=50\n",
    "\n",
    "for each_class in classification_mat:\n",
    "    if each_class[-2]<0.95:\n",
    "        weakpoint=int(each_class[0])\n",
    "       \n",
    "\n",
    "\n",
    "    #####################********** GAN Parameters  **************##############\n",
    "            \n",
    "        x_g=np.copy(x_partial)\n",
    "        y_g=np.zeros(y_partial.shape)\n",
    "        y_g[y_partial==weakpoint]=1\n",
    "\n",
    "        data = [(x, y) for x, y in zip(x_g,y_g)]\n",
    "        dataSet=Data_Loader(data)\n",
    "        data_loader = DataLoader(dataset=dataSet, batch_size=5000, shuffle=True)\n",
    "        discriminator = DiscriminatorNet()\n",
    "        generator = GeneratorNet()\n",
    "\n",
    "        ###########################################################\n",
    "        d_optimizer = optim.Adam(discriminator.parameters(), lr=0.0002)\n",
    "        g_optimizer = optim.Adam(generator.parameters(), lr=0.0002)\n",
    "\n",
    "        loss = nn.BCELoss()\n",
    "        ###########################################################\n",
    "        num_test_samples = 20\n",
    "        test_noise = noise(num_test_samples)\n",
    "\n",
    "        #*********************************************  Running GAN   ***************************\n",
    "        #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
    "        \n",
    "        num_epochs = 20\n",
    "        d_errs=[]\n",
    "        g_errs=[]\n",
    "\n",
    "        print(data_loader)\n",
    "        for epoch in range(num_epochs):\n",
    "            g_error_sum=0\n",
    "            d_error_sum=0\n",
    "            for n_batch, (real_batch,y_real) in enumerate(data_loader):\n",
    "                N = real_batch.size(0)\n",
    "\n",
    "                # 1. Train Discriminator\n",
    "                real_data = Variable(real_batch)\n",
    "                #real_target=Variable(real_target)\n",
    "                # Generate fake data and detach \n",
    "\n",
    "                #print(real_data.shape)\n",
    "\n",
    "                # (so gradients are not calculated for generator)\n",
    "                fake_data = generator(noise(N)).detach()\n",
    "\n",
    "                # Train D\n",
    "                y_real=np.array(y_real)\n",
    "                d_error, d_pred_real, d_pred_fake = train_discriminator(d_optimizer, real_data, fake_data,y_real)\n",
    "\n",
    "                # 2. Train Generator\n",
    "\n",
    "                # Generate fake data\n",
    "                fake_data = generator(noise(N))\n",
    "                # Train G\n",
    "                g_error = train_generator(g_optimizer, fake_data)\n",
    "\n",
    "                g_error_sum+=g_error\n",
    "\n",
    "                d_error_sum+=d_error\n",
    "\n",
    "\n",
    "            d_errs.append(d_error_sum)\n",
    "            g_errs.append(g_error_sum)  \n",
    "\n",
    "            if (epoch) % 10 == 0:\n",
    "                print(\"epoch: \",epoch)\n",
    "                test_noise = noise(num_test_samples)\n",
    "                test_images =(generator(test_noise))\n",
    "                test_images = test_images.data\n",
    "                real_data=real_data.data\n",
    "\n",
    "\n",
    "                plt.plot()\n",
    "                plt.scatter(real_data[:,0][y_real==1], real_data[:,1][y_real==1], s=40, marker='x',c='red')\n",
    "                plt.scatter(real_data[:,0][y_real==0], real_data[:,1][y_real==0], s=40, marker='o',c='blue')\n",
    "                plt.scatter(test_images[:,0], test_images[:,1], s=40, marker='p',c='green')\n",
    "                plt.axis('equal')\n",
    "                plt.show()\n",
    "\n",
    "                plt.plot()\n",
    "                plt.plot(d_errs)\n",
    "                plt.plot(g_errs)\n",
    "                plt.show()\n",
    "\n",
    "        ############  Generating and adding new samples  ###########\n",
    "        x_syn=(generator(noise(numOfSamples))).detach().numpy() \n",
    "        y_syn=np.ones(numOfSamples)*weakpoint\n",
    "        #************************************************\n",
    "        x_train=np.concatenate((x_train,x_syn),axis=0)\n",
    "        y_train=np.concatenate((y_train,y_syn),axis=0)\n",
    "        print(\"Shapes: \")\n",
    "        print(x_train.shape,y_train.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Running IDS again on GAN generated data "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "####################  DATA LOADING   #####################\n",
    "\n",
    "x_train = torch.from_numpy(x_train).type(torch.FloatTensor)\n",
    "x_test = torch.from_numpy(x_test).type(torch.FloatTensor)\n",
    "\n",
    "y_train = torch.from_numpy(y_train).type(torch.LongTensor)\n",
    "y_test = torch.from_numpy(y_test).type(torch.LongTensor)\n",
    "\n",
    "Training_data = [(x, y) for x, y in zip(x_train,y_train)]\n",
    "Testing_data = [(x, y) for x, y in zip(x_test,y_test)]\n",
    "        \n",
    "#######################  Train and Test Data Set  ##########################\n",
    "\n",
    "Training_DataSet=Data_Loader(Training_data)\n",
    "Testing_DataSet=Data_Loader(Testing_data)\n",
    "\n",
    "train_loader = DataLoader(dataset=Training_DataSet, batch_size=500, shuffle=True)\n",
    "testing_loader = DataLoader(dataset=Testing_DataSet, batch_size=len(Testing_DataSet), shuffle=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "########################## Running IDS Model ######################    \n",
    "\n",
    "model = ANN()\n",
    "F1_list_after=[]\n",
    "Pre_list=[]\n",
    "Report_after=[]\n",
    " \n",
    "#optimizer = optim.SGD(model.parameters(), lr=0.01)\n",
    "optimizer = optim.Adam(model.parameters(), lr = 0.001)\n",
    "criterion = nn.CrossEntropyLoss()\n",
    " \n",
    "for epoch in range(maxEpochforIDS):\n",
    "    correct_cnt, ave_loss = 0, 0\n",
    "    total_cnt = 0\n",
    "    for batch_idx, (x, target) in enumerate(train_loader):\n",
    "        optimizer.zero_grad()\n",
    "        out = model(x)\n",
    "        #print(out.data)\n",
    "        loss = criterion(out, target)\n",
    "        _, pred_label = torch.max(out.data, 1)\n",
    "        total_cnt += x.shape[0]\n",
    "        correct_cnt+= (pred_label == target).sum().item()\n",
    "        ave_loss = ave_loss * 0.9 + loss.item() * 0.1\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        if(epoch+1) % 20 == 0: #or (batch_idx+1) == len(testing_loader)\n",
    "            continue\n",
    "            print('==>>> epoch: {}, batch index: {}, train loss: {:.6f}, acc: {:.3f}'.format(\n",
    "                epoch, batch_idx+1, ave_loss, correct_cnt*1.0/total_cnt))\n",
    "    # testing\n",
    "    correct_cnt, ave_loss = 0, 0\n",
    "    total_cnt = 0\n",
    "    \n",
    "    \n",
    "    for batch_idx, (x, target) in enumerate(testing_loader):\n",
    "        #print(batch_idx,x.shape, target.shape)\n",
    "        out = model(x)\n",
    "        loss = criterion(out, target)\n",
    "        _, pred_label = torch.max(out.data, 1)\n",
    "        total_cnt += x.shape[0]\n",
    "        correct_cnt += (pred_label == target).sum().item()\n",
    "\n",
    "        # smooth average\n",
    "        ave_loss = ave_loss * 0.9 + loss.item() * 0.1\n",
    "       \n",
    "        if(epoch+1) % 1 == 0 or (batch_idx+1) == len(testing_loader):\n",
    "            F1= f1_score(target, pred_label, average=None)\n",
    "            Pre=precision_score(target, pred_label, average=None)\n",
    "            \n",
    "            # balancing number of labels\n",
    "            if np.array(F1).size!=labels_to_consider:\n",
    "                continue\n",
    "            F1_list_after.append(np.array(F1))\n",
    "            Pre_list.append(Pre)\n",
    "            plt.plot()\n",
    "            plt.plot(F1_list_after)\n",
    "            plt.show()\n",
    "            ##########################\n",
    "            y_true =target\n",
    "            y_pred = pred_label\n",
    "            Report_after.append(CR_mat(y_true,y_pred))\n",
    "                   \n",
    "#########################################################################################\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "##################  EVALUATING PERFORMANCE of IDS ########################\n",
    "y_true =target\n",
    "y_pred = pred_label\n",
    "print(classification_report(y_true, y_pred))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "############## Classification report after GAN \n",
    "import re\n",
    "report=classification_report(y_true, y_pred)\n",
    "classification_list=[]\n",
    "lines=report.split(\"\\n\")[2:-5]\n",
    "for line in lines:\n",
    "    line=re.sub(' +', ' ', line)\n",
    "    words=line.split(\" \")\n",
    "    if len(words)<5:\n",
    "        continue\n",
    "    print(words)\n",
    "    classification_list.append(words[1:])\n",
    "classification_mat=np.array(classification_list).astype(np.float)\n",
    "np.savetxt(\"classification_mat_after.txt\",classification_mat, fmt='%0.2f')"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "Nov_27.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
